/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.gammapeit.customjaas;

import com.gammapeit.customjaas.database.LdapDAO;
import com.gammapeit.customjaas.database.Usuario;
import com.gammapeit.customjaas.database.UsuarioJpaController;
import com.sun.appserv.security.AppservPasswordLoginModule;
import com.sun.enterprise.security.auth.realm.InvalidOperationException;
import com.sun.enterprise.security.auth.realm.NoSuchUserException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.security.auth.login.LoginException;
import org.glassfish.security.common.PrincipalImpl;

/**
 *
 * @author Mike
 */
public class LoginModule extends AppservPasswordLoginModule {

    public LoginModule() {
        System.out.println("CustomRealm LoginModule - Construction");
    }

    /**
     * Overrides the authenticateUser() method in AppservPasswordLoginModule
     * Performs authentication of user
     *
     * @throws javax.security.auth.login.LoginException
     */
    @Override
    protected void authenticateUser() throws LoginException {

        System.out.println("CustomRealm LoginModule authenticateUser(), _username:"
                + _username + ", _password:" + _password + ", _currentrealm:" + _currentRealm);

        if (!(_currentRealm instanceof CustomRealm)) {
            throw new LoginException("Realm not CustomRealm. Check 'login.conf'.");
        }
        CustomRealm myRealm = (CustomRealm) _currentRealm;

        // Authenticate User
        if (!doAuthentication(_username, _password)) {
            //Login failed
            throw new LoginException("CustomRealm LoginModule: Login Failed for user " + _username);
        }

        // Login succeeded
        System.out.println("CustomRealm LoginModule: Login Succeded for user " + _username);

        // Get group names for the authenticated user from the Realm class
        Enumeration enumeration = null;
        try {
            enumeration = myRealm.getGroupNames(_username);
        } catch (InvalidOperationException e) {
            throw new LoginException("InvalidOperationException was thrown for getGroupNames() on CustomRealm");
        } catch (NoSuchUserException e) {
            throw new LoginException("NoSuchUserException was thrown for getGroupNames() on CustomRealm");
        }

        // Convert the Enumeration to String[]
        List<String> g = new ArrayList<>();
        while (enumeration != null && enumeration.hasMoreElements()) {
            g.add((String) enumeration.nextElement());
        }

        String[] authenticatedGroups = g.toArray(new String[g.size()]);

        for (String grupo : authenticatedGroups) {
            System.out.println("nombre grupo " + grupo);
        }

        Set<Principal> principals = _subject.getPrincipals();

        principals.add(new PrincipalImpl(_username));

        for (Principal principal : principals) {
            System.out.println("Principal: " + principal);
        }

        // Call commitUserAuthentication with the group names the user belongs to.
        // Note that this method is called after the authentication has succeeded.
        // If authentication failed do not call this method. Global instance field
        // succeeded is set to true by this method.
        commitUserAuthentication(authenticatedGroups);
    }

    /**
     * Performs the authentication.
     */
    private boolean doAuthentication(String user, String password) {
        LdapDAO dao = LdapDAO.getInstance();

        if (dao.loginCorrect(user, password)) {
            System.out.println("Login LDAP Exitoso.");
            return true;
        } else {
            try {
                UsuarioJpaController control = new UsuarioJpaController();
                Usuario usr = control.findUsuarioByUsername(user);
                password = encriptarPassword(password);

                if (usr != null) {
                    System.out.println("Trajo el usuario!!!");
                    if (usr.getPassword().equals(password)) {
                        System.out.println("El password es el mismo!!!!");
                        return true;
                    }
                }
            } catch (Exception ex) {
                Logger.getLogger(LoginModule.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return false;
    }
    
    /**
     * Método que toma una cadena de caracteres y la pasa por el algoritmo de encripción MD5
     * y retorna la cadena de caracteres encriptada como una cadena de caracteres alfanumericos
     * del tipo Hexadecimal.
     * @param password, contraseña a ser encriptada.
     * @return String, Cadena de caracteres encriptada en formato hexadecimal.
     * @throws Exception, si no puede encriptar la cadena de caracteres.
     */
    public String encriptarPassword(String password) throws Exception {
        MessageDigest md;
        byte byteData[];
        try {
            md = MessageDigest.getInstance("MD5");
            md.update(password.getBytes());
            byteData = md.digest();

            //Se convierte el arreglo de bytes a una cadena de hexadecimales
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < byteData.length; i++) {
                sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
            }

            return sb.toString();
        } catch (NoSuchAlgorithmException ex) {
            throw new Exception("Error encriptando el password. | EJBSeguridad | encriptarPassword", ex);
        }
    }
}
